using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Linq;

namespace shacoEditor
{
    public class HybridAutoGenerateHelper
    {
        [MenuItem("HybridCLR/刷新热更新dll")]
        static void RefeshOutputDlls()
        {
            RefeshOutputDllsBase(true);
        }
        static public void RefeshOutputDllsBase(bool askPath)
        {
            string exportDllPath = shaco.GameHelper.datasave.ReadString("HybridAutoGenerateWindow.exportDllPath");
            void Execute()
            {
                if (string.IsNullOrEmpty(exportDllPath))
                    return;

                var hotupdateDllFilesName = AutoSyncHotUpdateDllNames();
                var hotupdateAOTDllFilesName = AutoSyncAotDllNames();
                if (hotupdateDllFilesName.IsNullOrEmpty())
                {
                    Debug.LogError("热更新dll设置为空，请在HybridCLR/Settings...中设置");
                    return;
                }
                if (hotupdateAOTDllFilesName.IsNullOrEmpty())
                {
                    Debug.LogError("热更新aot dll为空，请检查代码是否报错");
                    return;
                }
                CompileDllAndCopyToHotUpdateFolder(exportDllPath, hotupdateDllFilesName.ToArray(), hotupdateAOTDllFilesName.ToArray());
            };

            if (!askPath)
            {
                Execute();
                return;
            }
            
            shacoEditor.InputDialogWindow.Open("请选择要导出dll的路径", () =>
            {
                GUI.changed = false;
                exportDllPath = GUILayoutHelper.PathField("根目录", exportDllPath, string.Empty, Application.dataPath);
                if (GUI.changed)
                    shaco.GameHelper.datasave.WriteString("HybridAutoGenerateWindow.exportDllPath", exportDllPath);
            }, Execute);
        }

        static List<string> AutoSyncHotUpdateDllNames()
        {
            var hotupdateDllFilesName = new List<string>();
            foreach (var iter in HybridCLR.Editor.SettingsUtil.HybridCLRSettings.hotUpdateAssemblyDefinitions)
            {
                var assetPath = AssetDatabase.GetAssetPath(iter);
                var dllName = $"{System.IO.Path.GetFileNameWithoutExtension(assetPath)}.dll";
                hotupdateDllFilesName.Add(dllName);
            }
            return hotupdateDllFilesName;
        }

        static List<string> AutoSyncAotDllNames()
        {
            var outputAOTFilePath = $"{Application.dataPath}/{HybridCLR.Editor.SettingsUtil.HybridCLRSettings.outputAOTGenericReferenceFile}";

            var hotupdateAOTDllFilesName = new List<string>();
            var readString = System.IO.File.ReadAllText(outputAOTFilePath);
            var indexFind = readString.IndexOf(".dll");
            while (indexFind >= 0)
            {
                var indexStart = readString.LastIndexOf("\"", indexFind);
                var indexEnd = readString.IndexOf("\"", indexFind);
                if (indexStart < 0 || indexEnd < 0 || indexEnd < indexStart)
                {
                    Debug.LogError($"同步发生错误，未找到正确dll字符串标识, start{indexStart} end{indexEnd}");
                    break;
                }
                var dllName = readString.Substring(indexStart + 1, indexEnd - indexStart - 1);
                hotupdateAOTDllFilesName.Add(dllName);
                indexFind = readString.IndexOf(".dll", indexFind + 1);
            }
            return hotupdateAOTDllFilesName;
        }

        static void CompileDllAndCopyToHotUpdateFolder(string exportDllPath, string[] hotupdateDllFilesName, string[] hotupdateAOTDllFilesName)
        {
            var activeBuildTarget = UnityEditor.EditorUserBuildSettings.activeBuildTarget;
            HybridCLR.Editor.Commands.CompileDllCommand.CompileDll(activeBuildTarget);

            var outputDir = HybridCLR.Editor.SettingsUtil.GetHotUpdateDllsOutputDirByTarget(activeBuildTarget);
            var outputDir2 = HybridCLR.Editor.SettingsUtil.GetAssembliesPostIl2CppStripDir(activeBuildTarget);
            var hotupdateDllSubDir = exportDllPath;
            var hotupdateDllDir = Application.dataPath.Remove("/Assets") + $"/{hotupdateDllSubDir}";
            var hotupdateAOTDllDir = hotupdateDllDir + "/AOT";

            if (System.IO.Directory.GetFiles(outputDir2).Length <= 0)
            {
                Debug.Log("AssembliesPostIl2CppStrip目录文件缺失，重新编译下");
                HybridCLR.Editor.Commands.StripAOTDllCommand.GenerateStripedAOTDlls();
            }

            var hotupdateDll = new List<string>();
            hotupdateDll.AddRange(hotupdateDllFilesName);
            foreach (var iter in hotupdateDll)
            {
                var copyFrom = $"{outputDir}/{iter}";
                var pasteTo = $"{hotupdateDllDir}/{iter}.bytes";
                System.IO.File.Copy(copyFrom, pasteTo, true);
            }
            var assetDir = AssetDatabase.LoadAssetAtPath<Object>(hotupdateDllSubDir);
            Debug.Log("copy main dll finished, path=" + hotupdateDllSubDir, assetDir);

            foreach (var iter in hotupdateAOTDllFilesName)
            {
                var copyFrom = $"{outputDir}/{iter}";
                if (!System.IO.File.Exists(copyFrom))
                    copyFrom = $"{outputDir2}/{iter}";
                var pasteTo = $"{hotupdateAOTDllDir}/{iter}.bytes";

                var pasteToFolderPath = System.IO.Path.GetDirectoryName(pasteTo);
                if (!System.IO.Directory.Exists(pasteToFolderPath))
                    System.IO.Directory.CreateDirectory(pasteToFolderPath);
                System.IO.File.Copy(copyFrom, pasteTo, true);
            }

            var assetDir2 = AssetDatabase.LoadAssetAtPath<Object>(ConvertAbsoluteToAssetRelativePath(hotupdateAOTDllDir));
            Debug.Log("copy aot finished, path=" + hotupdateDllSubDir, assetDir2);

            AssetDatabase.Refresh();
        }

        [MenuItem("HybridCLR/查找项目asmdef依赖", false)]
        static void FindAssemblyDepencies()
        {
            var includeAssembly = HybridCLR.Editor.SettingsUtil.HotUpdateAssemblyFilesIncludePreserved;
            var includeAssemblyGUID = new List<string>();
            var allAsmdefAssetPath = AssetDatabase.FindAssets("t:asmdef", new string[] { "Assets" }).Select(v => AssetDatabase.GUIDToAssetPath(v));
            var allAsmdefAssetPathDic = new Dictionary<string, string>();
            foreach (var iter in allAsmdefAssetPath)
            {
                var fileName = System.IO.Path.GetFileNameWithoutExtension(iter);
                if (allAsmdefAssetPathDic.TryGetValue(fileName, out var findValue))
                {
                    Debug.LogError("重复的路径=" + iter + " \n添加过的路径=" + findValue);
                    continue;
                }
                allAsmdefAssetPathDic.Add(fileName, iter);
            }

            foreach (var iter in includeAssembly)
            {
                var fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(iter);
                if (!allAsmdefAssetPathDic.TryGetValue(fileNameWithoutExtension, out var findValue))
                {
                    Debug.LogError("没有找到hybrid热更新dll路径=" + iter);
                    continue;
                }
                includeAssemblyGUID.Add(AssetDatabase.AssetPathToGUID(findValue));
            }

            var asmdef = Selection.objects.Where(v => v.GetType() == typeof(UnityEditorInternal.AssemblyDefinitionAsset)).Select(v => (UnityEditorInternal.AssemblyDefinitionAsset)v);
            var referencedAsmdefAssetPath = shaco.Instance.FindReference.FindAsmdefReferenceTool.FindAssemblyDepencies(asmdef, includeAssemblyGUID);
            foreach (var iter in referencedAsmdefAssetPath)
            {
                var subAsmdef = AssetDatabase.LoadAssetAtPath<UnityEditorInternal.AssemblyDefinitionAsset>(iter);
                shaco.Instance.FindReference.FindAsmdefReferenceTool.FindAssemblyDepencies(subAsmdef, includeAssemblyGUID);
            }
        }

        [MenuItem("HybridCLR/查找项目asmdef依赖", true)]
        static bool FindAssemblyDepenciesValid()
        {
            return Selection.objects.Any(v => v.GetType() == typeof(UnityEditorInternal.AssemblyDefinitionAsset));
        }

        public static string ConvertAbsoluteToAssetRelativePath(string absolutePath)
        {
            // 标准化路径格式
            string dataPath = System.IO.Path.GetFullPath(Application.dataPath).Replace("\\", "/");
            absolutePath = System.IO.Path.GetFullPath(absolutePath).Replace("\\", "/");

            // 检查是否在Assets目录下
            if (!absolutePath.StartsWith(dataPath))
            {
                Debug.LogError($"路径不在项目根目录内{Application.dataPath}");
                return null;
            }

            // 截取相对路径并拼接"Assets"
            string relativePath = "Assets" + absolutePath.Substring(dataPath.Length);
            return relativePath;
        }
    }
}
